/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "peripheral_switch_control.h"
#include "peripheral_uart.h"
#include "common_config_manager.h"
#include "utils_log.h"
#include <vector>
#include <algorithm>

namespace El {
namespace Peripheral {

// 静态常量定义 - 串口控制命令
const std::string SwitchControl::BROADCAST_ON_CMD = "010600000001480A";
const std::string SwitchControl::BROADCAST_OFF_CMD = "01060000000089CA";
const std::string SwitchControl::WARNING_LIGHT_ON_CMD = "01060001000119CA";
const std::string SwitchControl::WARNING_LIGHT_OFF_CMD = "010600010000D80A";
const std::string SwitchControl::SPARE1_ON_CMD = "010600020001E9CA";
const std::string SwitchControl::SPARE1_OFF_CMD = "010600020000280A";
const std::string SwitchControl::SPARE2_ON_CMD = "010600030001B80A";
const std::string SwitchControl::SPARE2_OFF_CMD = "01060003000079CA";

SwitchControl::SwitchControl()
    : initialized_(false)
    , uartName_("ttyAMA2")  // 默认使用ttyAMA2串口
    , broadcastEnabled_(false)
    , warningLightEnabled_(false)
    , spare1Enabled_(false)
    , spare2Enabled_(false)
    , broadcastListenerId_(-1)
    , warningLightListenerId_(-1)
    , spare1ListenerId_(-1)
    , spare2ListenerId_(-1)
{
}

SwitchControl::~SwitchControl()
{
    Stop();
}

SwitchControl &SwitchControl::GetInstance()
{
    static SwitchControl instance;
    return instance;
}

bool SwitchControl::Start()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (initialized_) {
        EL_INFO("Switch control service already started");
        return true;
    }

    // 确保UART管理器已初始化
    if (!UartManager::GetInstance().IsUartInitialized(uartName_)) {
        EL_ERROR("UART {} not initialized, cannot start switch control service", uartName_);
        return false;
    }

    // 读取当前配置状态
    try {
        auto config = El::Common::ConfigManager::GetInstance().GetConfig("/switch_control");
        if (!config.is_null()) {
            if (config.contains("broadcast") && config["broadcast"].contains("enabled")) {
                broadcastEnabled_ = config["broadcast"]["enabled"];
            }
            if (config.contains("warning_light") && config["warning_light"].contains("enabled")) {
                warningLightEnabled_ = config["warning_light"]["enabled"];
            }
            if (config.contains("spare1") && config["spare1"].contains("enabled")) {
                spare1Enabled_ = config["spare1"]["enabled"];
            }
            if (config.contains("spare2") && config["spare2"].contains("enabled")) {
                spare2Enabled_ = config["spare2"]["enabled"];
            }
        }
    } catch (const std::exception& e) {
        EL_WARN("Failed to read switch control configuration: {}", e.what());
    }

    // 注册配置监听器
    auto& configManager = El::Common::ConfigManager::GetInstance();

    // 注册广播配置监听器
    broadcastListenerId_ = configManager.Register("/switch_control/broadcast",
        [this](const nlohmann::json &config) -> bool {
            return OnBroadcastConfigChanged(config);
        });

    // 注册警灯配置监听器
    warningLightListenerId_ = configManager.Register("/switch_control/warning_light",
        [this](const nlohmann::json &config) -> bool {
            return OnWarningLightConfigChanged(config);
        });

    // 注册备用1配置监听器
    spare1ListenerId_ = configManager.Register("/switch_control/spare1",
        [this](const nlohmann::json &config) -> bool {
            return OnSpare1ConfigChanged(config);
        });

    // 注册备用2配置监听器
    spare2ListenerId_ = configManager.Register("/switch_control/spare2",
        [this](const nlohmann::json &config) -> bool {
            return OnSpare2ConfigChanged(config);
        });

    if (broadcastListenerId_ < 0 || warningLightListenerId_ < 0 ||
        spare1ListenerId_ < 0 || spare2ListenerId_ < 0) {
        EL_ERROR("Failed to register configuration listeners");
        Stop();
        return false;
    }

    initialized_ = true;

    // 根据配置状态发送初始命令到串口，确保硬件状态与配置同步
    EL_INFO("Synchronizing hardware state with configuration...");

    // 发送广播命令
    const std::string& broadcastCmd = broadcastEnabled_ ? BROADCAST_ON_CMD : BROADCAST_OFF_CMD;
    if (!SendCommand(broadcastCmd)) {
        EL_WARN("Failed to send initial broadcast command: {}", broadcastEnabled_ ? "ON" : "OFF");
    }

    // 发送警灯命令
    const std::string& warningCmd = warningLightEnabled_ ? WARNING_LIGHT_ON_CMD : WARNING_LIGHT_OFF_CMD;
    if (!SendCommand(warningCmd)) {
        EL_WARN("Failed to send initial warning light command: {}", warningLightEnabled_ ? "ON" : "OFF");
    }

    // 发送备用1命令
    const std::string& spare1Cmd = spare1Enabled_ ? SPARE1_ON_CMD : SPARE1_OFF_CMD;
    if (!SendCommand(spare1Cmd)) {
        EL_WARN("Failed to send initial spare1 command: {}", spare1Enabled_ ? "ON" : "OFF");
    }

    // 发送备用2命令
    const std::string& spare2Cmd = spare2Enabled_ ? SPARE2_ON_CMD : SPARE2_OFF_CMD;
    if (!SendCommand(spare2Cmd)) {
        EL_WARN("Failed to send initial spare2 command: {}", spare2Enabled_ ? "ON" : "OFF");
    }

    EL_INFO("Switch control service started successfully, using UART: {}", uartName_);
    EL_INFO("Current status - Broadcast: {}, Warning Light: {}, Spare1: {}, Spare2: {}",
            broadcastEnabled_ ? "ON" : "OFF",
            warningLightEnabled_ ? "ON" : "OFF",
            spare1Enabled_ ? "ON" : "OFF",
            spare2Enabled_ ? "ON" : "OFF");

    return true;
}

bool SwitchControl::Stop()
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!initialized_) {
        return true;
    }

    // 取消配置监听器注册
    auto& configManager = El::Common::ConfigManager::GetInstance();

    if (broadcastListenerId_ >= 0) {
        configManager.Unregister("/switch_control/broadcast", broadcastListenerId_);
        broadcastListenerId_ = -1;
    }

    if (warningLightListenerId_ >= 0) {
        configManager.Unregister("/switch_control/warning_light", warningLightListenerId_);
        warningLightListenerId_ = -1;
    }

    if (spare1ListenerId_ >= 0) {
        configManager.Unregister("/switch_control/spare1", spare1ListenerId_);
        spare1ListenerId_ = -1;
    }

    if (spare2ListenerId_ >= 0) {
        configManager.Unregister("/switch_control/spare2", spare2ListenerId_);
        spare2ListenerId_ = -1;
    }

    initialized_ = false;
    EL_INFO("Switch control service stopped");

    return true;
}

bool SwitchControl::OnBroadcastConfigChanged(const nlohmann::json &config)
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!initialized_) {
        EL_WARN("Switch control service not started, ignoring broadcast configuration change");
        return false;
    }

    try {
        if (config.contains("enabled") && config["enabled"].is_boolean()) {
            bool newState = config["enabled"];
            if (newState != broadcastEnabled_) {
                const std::string& command = newState ? BROADCAST_ON_CMD : BROADCAST_OFF_CMD;
                if (SendCommand(command)) {
                    broadcastEnabled_ = newState;
                    EL_INFO("Broadcast switch status updated: {}", newState ? "ON" : "OFF");
                    return true;
                } else {
                    EL_ERROR("Broadcast switch control failed: {}", newState ? "ON" : "OFF");
                    return false;
                }
            }
        }
    } catch (const std::exception& e) {
        EL_ERROR("Failed to handle broadcast configuration change: {}", e.what());
        return false;
    }

    return true;
}

bool SwitchControl::OnWarningLightConfigChanged(const nlohmann::json &config)
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!initialized_) {
        EL_WARN("Switch control service not started, ignoring warning light configuration change");
        return false;
    }

    try {
        if (config.contains("enabled") && config["enabled"].is_boolean()) {
            bool newState = config["enabled"];
            if (newState != warningLightEnabled_) {
                const std::string& command = newState ? WARNING_LIGHT_ON_CMD : WARNING_LIGHT_OFF_CMD;
                if (SendCommand(command)) {
                    warningLightEnabled_ = newState;
                    EL_INFO("Warning light switch status updated: {}", newState ? "ON" : "OFF");
                    return true;
                } else {
                    EL_ERROR("Warning light switch control failed: {}", newState ? "ON" : "OFF");
                    return false;
                }
            }
        }
    } catch (const std::exception& e) {
        EL_ERROR("Failed to handle warning light configuration change: {}", e.what());
        return false;
    }

    return true;
}

bool SwitchControl::OnSpare1ConfigChanged(const nlohmann::json &config)
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!initialized_) {
        EL_WARN("Switch control service not started, ignoring spare1 configuration change");
        return false;
    }

    try {
        if (config.contains("enabled") && config["enabled"].is_boolean()) {
            bool newState = config["enabled"];
            if (newState != spare1Enabled_) {
                const std::string& command = newState ? SPARE1_ON_CMD : SPARE1_OFF_CMD;
                if (SendCommand(command)) {
                    spare1Enabled_ = newState;
                    EL_INFO("Spare1 switch status updated: {}", newState ? "ON" : "OFF");
                    return true;
                } else {
                    EL_ERROR("Spare1 switch control failed: {}", newState ? "ON" : "OFF");
                    return false;
                }
            }
        }
    } catch (const std::exception& e) {
        EL_ERROR("Failed to handle spare1 configuration change: {}", e.what());
        return false;
    }

    return true;
}

bool SwitchControl::OnSpare2ConfigChanged(const nlohmann::json &config)
{
    std::lock_guard<std::mutex> lock(mutex_);

    if (!initialized_) {
        EL_WARN("Switch control service not started, ignoring spare2 configuration change");
        return false;
    }

    try {
        if (config.contains("enabled") && config["enabled"].is_boolean()) {
            bool newState = config["enabled"];
            if (newState != spare2Enabled_) {
                const std::string& command = newState ? SPARE2_ON_CMD : SPARE2_OFF_CMD;
                if (SendCommand(command)) {
                    spare2Enabled_ = newState;
                    EL_INFO("Spare2 switch status updated: {}", newState ? "ON" : "OFF");
                    return true;
                } else {
                    EL_ERROR("Spare2 switch control failed: {}", newState ? "ON" : "OFF");
                    return false;
                }
            }
        }
    } catch (const std::exception& e) {
        EL_ERROR("Failed to handle spare2 configuration change: {}", e.what());
        return false;
    }

    return true;
}

bool SwitchControl::SendCommand(const std::string &command)
{
    // 获取串口对象
    Com *uart = UartManager::GetInstance().GetUart(uartName_);
    if (!uart) {
        EL_ERROR("Unable to get UART object: {}", uartName_);
        return false;
    }

    // 将十六进制字符串转换为字节数组
    std::vector<uint8_t> data = HexStringToBytes(command);
    if (data.empty()) {
        EL_ERROR("Invalid command format: {}", command);
        return false;
    }

    // 发送数据
    int32_t result = uart->Write(data.data(), data.size());
    if (result < 0) {
        EL_ERROR("UART send failed, return value: {}", result);
        return false;
    }

    EL_DEBUG("UART command sent successfully: {} (length: {})", command, data.size());
    return true;
}

std::vector<uint8_t> SwitchControl::HexStringToBytes(const std::string &hexStr)
{
    std::vector<uint8_t> bytes;

    if (hexStr.length() % 2 != 0) {
        EL_ERROR("Hex string length must be even: {}", hexStr);
        return bytes;
    }

    for (size_t i = 0; i < hexStr.length(); i += 2) {
        std::string byteString = hexStr.substr(i, 2);
        try {
            uint8_t byte = static_cast<uint8_t>(std::stoul(byteString, nullptr, 16));
            bytes.push_back(byte);
        } catch (const std::exception& e) {
            EL_ERROR("Failed to convert hex string: {}, error: {}", byteString, e.what());
            bytes.clear();
            return bytes;
        }
    }

    return bytes;
}

} // namespace Peripheral
} // namespace El